package com.chinalin.h5_webrtc_host

import android.annotation.SuppressLint
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.net.http.SslError
import android.os.Build
import android.os.Message
import android.util.Log
import android.view.View
import android.webkit.ConsoleMessage
import android.webkit.GeolocationPermissions
import android.webkit.JsResult
import android.webkit.PermissionRequest
import android.webkit.SslErrorHandler
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.FrameLayout
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity

object WebViewUtils {

    fun setupSuperWebView(
        webView: WebView,
        activity: AppCompatActivity,
        fileChooserLauncher: ActivityResultLauncher<Intent>,
        onFileUploadCallbackSet: (ValueCallback<Array<Uri>>?) -> Unit,
        onProgress: (Int) -> Unit,
        onUrlChanged: (String) -> Unit,
    ) {
        applySuperSettings(webView.settings)
        webView.webViewClient = SuperWebViewClient(onUrlChanged)
        webView.webChromeClient =
            SuperWebChromeClient(activity, fileChooserLauncher, onFileUploadCallbackSet, onProgress)
    }

    @SuppressLint("SetJavaScriptEnabled")
    private fun applySuperSettings(settings: WebSettings) {
        // --- 核心功能权限 ---
        settings.javaScriptEnabled = true
        settings.domStorageEnabled = true
        settings.databaseEnabled = true
        settings.allowFileAccess = true
        settings.javaScriptCanOpenWindowsAutomatically = true
        settings.setSupportMultipleWindows(true)

        // --- 媒体和资源权限 ---
        settings.mediaPlaybackRequiresUserGesture = false
        settings.allowContentAccess = true
        settings.allowFileAccessFromFileURLs = true
        settings.allowUniversalAccessFromFileURLs = true

        // --- WebRTC 和高级 API 权限 ---
        settings.setGeolocationEnabled(true)

        // --- 渲染和兼容性配置 ---
        settings.useWideViewPort = true
        settings.loadWithOverviewMode = true
        settings.setSupportZoom(true)
        settings.builtInZoomControls = true
        settings.displayZoomControls = false

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            settings.safeBrowsingEnabled = false
        }

        settings.blockNetworkImage = false
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
        }

        // --- 性能优化 ---
        //settings.setAppCacheEnabled(true)
        settings.cacheMode = WebSettings.LOAD_DEFAULT
    }

    private class SuperWebViewClient(
        private val onUrlChanged: (String) -> Unit,
    ) : WebViewClient() {
        companion object {
            private const val TAG = "SuperWebViewClient"
        }

        override fun shouldOverrideUrlLoading(
            view: WebView?,
            request: WebResourceRequest?
        ): Boolean {
            view ?: return false
            val url: Uri = request?.url ?: return false // 获取请求的 URL
            val urlString = url.toString()
            Log.d(TAG, "URL loading requested: $urlString")

            // 1. 判断是否是标准的网页链接 (http 或 https)
            if ("http" == url.scheme || "https" == url.scheme) {
                // 对于标准的网页链接，我们总是希望 WebView 在内部处理。
                // 返回 false 会让 WebView 继续加载这个 URL。
                // 网页内部的服务器端重定向（301/302）会触发 WebView 加载新 URL，
                // 再次进入此方法，我们同样返回 false，从而实现了重定向的自动处理。
                onUrlChanged.invoke(urlString)
                return false
            }

            // 2. 如果不是网页链接，则尝试用系统其他应用打开 (拦截处理)
            // 例如：tel:, mailto:, market:, myapp:// 等自定义协议
            AlertDialog.Builder(view.context)
                .setTitle("重定向")
                .setMessage("是否允许打开${url}？")
                .setNegativeButton(
                    "拒绝"
                ) { dialog, _ -> dialog.dismiss() }
                .setPositiveButton("同意") { _, _ ->
                    try {
                        val intent = Intent(Intent.ACTION_VIEW, url)
                        // 添加这个 Flag，如果是在 Activity 之外的 Context（如 Service）中启动 Activity，是必须的。
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                        view.context.startActivity(intent)
                    } catch (e: ActivityNotFoundException) {
                        Log.w(TAG, "No activity found to handle URL: $urlString")
                        // 如果没有找到可以处理此 URL 的应用，也返回 true。
                        // 这可以防止 WebView 尝试加载一个它无法识别的协议，从而显示一个错误页面。
                    }
                }.show()
            return true
        }

        @SuppressLint("WebViewClientOnReceivedSslError")
        override fun onReceivedSslError(
            view: WebView?,
            handler: SslErrorHandler?,
            error: SslError?
        ) {
            Log.w(TAG, "SSL Error: $error. Proceeding anyway.")
            view?.let {
                Toast.makeText(it.context, "onReceivedSslError: $error", Toast.LENGTH_SHORT).show()
            }
            handler?.proceed()
        }
    }

    private class SuperWebChromeClient(
        private val activity: AppCompatActivity,
        private val fileChooserLauncher: ActivityResultLauncher<Intent>,
        private val onFileUploadCallbackSet: (ValueCallback<Array<Uri>>?) -> Unit,
        private val onProgress: (Int) -> Unit
    ) : WebChromeClient() {
        companion object {
            private const val TAG = "SuperWebChromeClient"
        }

        private var customView: View? = null

        override fun onPermissionRequest(request: PermissionRequest?) {
            Log.d(TAG, "onPermissionRequest for: ${request?.resources?.joinToString()}")
            request?.grant(request.resources)
        }

        override fun onGeolocationPermissionsShowPrompt(
            origin: String?,
            callback: GeolocationPermissions.Callback?
        ) {
            Log.d(TAG, "onGeolocationPermissionsShowPrompt for origin: $origin")
            callback?.invoke(origin, true, false)
        }

        override fun onJsAlert(
            view: WebView?,
            url: String?,
            message: String?,
            result: JsResult?
        ): Boolean {
            AlertDialog.Builder(activity)
                .setTitle("Alert")
                .setMessage(message)
                .setPositiveButton("OK") { _, _ -> result?.confirm() }
                .setCancelable(false)
                .show()
            return true
        }

        override fun onJsConfirm(
            view: WebView?,
            url: String?,
            message: String?,
            result: JsResult?
        ): Boolean {
            AlertDialog.Builder(activity)
                .setTitle("Confirm")
                .setMessage(message)
                .setPositiveButton("OK") { _, _ -> result?.confirm() }
                .setNegativeButton("Cancel") { _, _ -> result?.cancel() }
                .setCancelable(false)
                .show()
            return true
        }

        override fun onShowFileChooser(
            webView: WebView?,
            filePathCallback: ValueCallback<Array<Uri>>?,
            fileChooserParams: FileChooserParams?
        ): Boolean {
            onFileUploadCallbackSet(null) // Reset previous callback
            onFileUploadCallbackSet(filePathCallback)

            val intent = fileChooserParams?.createIntent()
            try {
                fileChooserLauncher.launch(intent)
            } catch (e: Exception) {
                onFileUploadCallbackSet(null)
                Log.e(TAG, "Cannot launch file chooser", e)
                return false
            }
            return true
        }

        override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
            val message =
                "${consoleMessage?.message()} -- From line ${consoleMessage?.lineNumber()} of ${consoleMessage?.sourceId()}"
            Log.d("WebViewConsole", message)
            return true
        }

        override fun onShowCustomView(view: View?, callback: CustomViewCallback?) {
            if (customView != null) {
                callback?.onCustomViewHidden()
                return
            }
            this.customView = view
            val decorView = activity.window.decorView as FrameLayout
            decorView.addView(this.customView, FrameLayout.LayoutParams.MATCH_PARENT)
        }

        override fun onHideCustomView() {
            val decorView = activity.window.decorView as FrameLayout
            decorView.removeView(customView)
            this.customView = null
        }

        override fun onCreateWindow(
            view: WebView?,
            isDialog: Boolean,
            isUserGesture: Boolean,
            resultMsg: Message?
        ): Boolean {
            val newWebView = WebView(activity)
            // 简单配置，防止新窗口无法使用js
            newWebView.settings.javaScriptEnabled = true
            val transport = resultMsg?.obj as? WebView.WebViewTransport
            transport?.webView = newWebView
            resultMsg?.sendToTarget()
            Log.d(TAG, "New window requested")
            // 你可以决定如何展示这个 newWebView，例如弹出一个新的 Dialog
            return true
        }

        override fun onProgressChanged(view: WebView?, newProgress: Int) {
            super.onProgressChanged(view, newProgress)
            onProgress.invoke(newProgress)
        }

    }
}